/*
 * Copyright 2020 www.mytijian.com All right reserved. This software is the
 * confidential and proprietary information of www.mytijian.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with www.mytijian.com.
 */
package com.mytijian.task.controller.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mytijian.base.exception.AppException;
import com.mytijian.base.exception.BizSystemException;
import com.mytijian.base.exception.ErrorInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@Component
public class JsonExceptionHandler implements HandlerExceptionResolver {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private ObjectMapper mapper = new ObjectMapper();
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
                                         Exception ex) {

        try {
            Map<String, Object> error = new HashMap<String, Object>();
            error.put("type", "danger");
            if (ex instanceof AppException) {
                AppException e = (AppException) ex;
                error.put("code", e.getErrorCode());
                error.put("text", e.getMessage());
                error.put("extInfo", e.getExtInfo());
            } else {
                int randomCode = new Random().nextInt(1000000);
                error.put("show", true);
                error.put("code", SysExceptionEnum.SYSTEM_ERROR.getErrorCode());
                error.put("text", "系统异常，错误码：[" + randomCode + "]，请联系管理员！");
                errorlog(request, new BizSystemException(SysExceptionEnum.SYSTEM_ERROR, ex), randomCode,
                        "Uncatched Error occued!");
            }
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            mapper.writeValue(response.getWriter(), error);
        } catch (IOException e) {
            logger.error("处理异常出错 e= {}", e);
        }
        return new ModelAndView();

    }

    private void errorlog(HttpServletRequest request, Exception ex, int code, String message) {
        StringBuilder sb = new StringBuilder();
        Enumeration<?> params = request.getParameterNames();
        while (params.hasMoreElements()) {
            String paramName = (String) params.nextElement();
            String value = request.getParameter(paramName);
            if (value != null) {
                if (paramName.toUpperCase().startsWith("PASSWORD")) {
                    value = value.replaceAll(".", "*");
                }
                sb.append("\t\t" + paramName + " = " + value + "\n");
            }
        }

        StringBuilder sb1 = new StringBuilder();
        Enumeration<?> attributes = request.getParameterNames();
        while (attributes.hasMoreElements()) {
            String paramName = (String) attributes.nextElement();
            Object value = request.getAttribute(paramName);
            if (value != null) {
                sb1.append("\t\t" + paramName + " = " + value + "\n");
            }
        }
        // TODO log post content

        String msg = String.format("%s, ErrorCode:%s,\n url: %s\n param: %s\n attr:%s", message, code,
                request.getRequestURL(), sb, sb1);

        logger.error(msg, ex);
    }

    static enum SysExceptionEnum implements ErrorInfo {

        /**
         * 系统错误
         */
        SYSTEM_ERROR("EX_0_0_SYS_00_00_000", "系统服务发生异常，请联系管理员！");

        private String errorCode;
        private String errorMsg;

        private SysExceptionEnum(String errorCode, String errorMsg) {
            this.errorCode = errorCode;
            this.errorMsg = errorMsg;
        }

        @Override
        public String getErrorCode() {
            return errorCode;
        }

        @Override
        public String getErrorMsg() {
            return errorMsg;
        }

    }

}
